package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.converter.PayConverter;
import com.cskaoyan.wordmemorize.dao.entity.LevelDO;
import com.cskaoyan.wordmemorize.dao.entity.UserDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocBoundLogDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocBoundStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.VocPaySaleDO;
import com.cskaoyan.wordmemorize.dao.mapper.LevelMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocBoundLogMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocBoundStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.VocPaySaleMapper;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.app.PayOrderDTO;
import com.cskaoyan.wordmemorize.dto.app.VocPaySaleDTO;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.PaySuccessNotifyCommand;
import com.cskaoyan.wordmemorize.request.VocPaySaleCommand;
import com.cskaoyan.wordmemorize.service.UserPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.List;

@Service
public class UserPayServiceImpl implements UserPayService {

    @Autowired
    VocPaySaleMapper vocPaySaleMapper;
    @Autowired
    UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;
    @Autowired
    UserVocBoundLogMapper userVocBoundLogMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    LevelMapper levelMapper;
    @Autowired
    PayConverter payConverter;

    /**
     * 用户用于支付
     *
     * @param command
     * @param userId
     * @return
     */
    @Override
    @Transactional
    public PayOrderDTO pay(VocPaySaleCommand command, Long userId) {
        // 补签卡唯一校验
        if (command.getItemType() != null && command.getItemType() == 3) {
            UserDO user = userMapper.selectById(userId);
            if (user != null && user.getHasSignCard() != null && user.getHasSignCard() == 1) {
                throw new RuntimeException("用户已拥有补签卡，不能重复购买");
            }
        }
        // 保存支付交易，status=1（初始化）
        VocPaySaleDO paySale = new VocPaySaleDO();
        paySale.setUserId(userId);
        if (command.getItemId() != null) {
            try {
                paySale.setItemId(Long.valueOf(command.getItemId()));
            } catch (Exception ignore) {
            }
        }
        paySale.setItemName(command.getItemName());
        paySale.setItemType(command.getItemType());
        paySale.setPayPrice(command.getPayPrice());
        paySale.setStatus(1); // 初始化
        paySale.setIsDeleted(0);
        vocPaySaleMapper.insert(paySale);
        // 返回支付交易id
        PayOrderDTO dto = new PayOrderDTO();
        dto.setId(paySale.getId() == null ? null : paySale.getId().toString());
        return dto;
    }

    /**
     * 用户用于接收支付成功的异步通知
     *
     * @param command
     * @param userId
     * @return
     */
    @Override
    @Transactional
    public String paySuccess(PaySuccessNotifyCommand command, Long userId) {
        // 1. 根据支付交易id查voc_pay_sale
        VocPaySaleDO paySale = vocPaySaleMapper.selectById(command.getId());
        if (paySale == null || paySale.getStatus() == 2) {
            return "success"; // 幂等
        }
        // 2. 根据itemType做不同业务处理
        if (paySale.getItemType() == 1) {
            // 单词上限：更新voc_bound_statistics、插入voc_bound_log
            UserVocBoundStatisticsDO stat = userVocBoundStatisticsMapper.selectOne(
                    new LambdaQueryWrapper<UserVocBoundStatisticsDO>()
                            .eq(UserVocBoundStatisticsDO::getUserId, paySale.getUserId()));

            int addCount;
            if (paySale.getPayPrice() == null) {
                addCount = 0;
            } else {
                switch (paySale.getPayPrice().intValue()) {
                    case 8:
                        addCount = 500;
                        break;
                    case 12:
                        addCount = 800;
                        break;
                    case 25:
                        addCount = 1800;
                        break;
                    case 50:
                        addCount = 4000;
                        break;
                    default:
                        addCount = 0;
                }
            }

            if (stat == null) {
                stat = UserVocBoundStatisticsDO.builder()
                        .userId(paySale.getUserId())
                        .pay(addCount)
                        .total(addCount)
                        .available(addCount)
                        .free(0)
                        .exchange(0)
                        .occupied(0)
                        .build();
                userVocBoundStatisticsMapper.insert(stat);
            } else {
                stat.setPay((stat.getPay() == null ? 0 : stat.getPay()) + addCount);
                stat.setTotal((stat.getTotal() == null ? 0 : stat.getTotal()) + addCount);
                stat.setAvailable((stat.getAvailable() == null ? 0 : stat.getAvailable()) + addCount);
                userVocBoundStatisticsMapper.updateById(stat);
            }
            // 日志
            UserVocBoundLogDO log = UserVocBoundLogDO.builder()
                    .userId(paySale.getUserId())
                    .paySaleId(paySale.getId())
                    .type(1)
                    .logDate(LocalDate.now())
                    .count(addCount)
                    .description("购买单词上限")
                    .build();
            userVocBoundLogMapper.insert(log);
        } else if (paySale.getItemType() == 2) {
            // 等级解锁：根据金额和当前等级，按价格表升级
            UserDO user = userMapper.selectById(paySale.getUserId());
            if (user != null && paySale.getPayPrice() != null) {
                // 存储每个等级对应的升级所需价格，数组下标代表等级 0不用
                int[] levelPrice = { 0, 1, 2, 3, 4, 5, 6, 7, 10, 13, 16, 19, 22 };
                // 获取用户当前等级，若用户等级为空则默认为0
                int currentLevel = user.getLevelValue() == null ? 0 : user.getLevelValue();
                // 定义最高等级为12级
                int maxLevel = 12;
                // 获取用户支付金额的整数值
                int pay = paySale.getPayPrice().intValue();
                // 初始化目标等级为当前等级
                int targetLevel = currentLevel;

                for (int i = currentLevel + 1; i <= maxLevel; i++) {
                    // 判断支付金额是否足够升级到当前遍历的等级
                    if (pay >= levelPrice[i]) {
                        // 若足够，则将目标等级更新为当前遍历的等级
                        targetLevel = i;
                    } else {
                        // 若不足，则跳出循环
                        break;
                    }
                }
                if (targetLevel > currentLevel) {
                    // 若目标等级大于当前等级，则更新用户等级和等级日期
                    user.setLevelValue(targetLevel);
                    // 查询等级名称
                    LevelDO levelDO = levelMapper.selectOne(
                            new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<LevelDO>()
                                    .eq(LevelDO::getLevelValue, targetLevel)
                                    .eq(LevelDO::getIsDeleted, 0));
                    if (levelDO != null) {
                        user.setLevelName(levelDO.getLevelName());
                    }
                    // 更新用户等级更新日期为当前日期
                    user.setLevelDate(LocalDate.now());

                    userMapper.updateById(user);
                }
            }
        } else if (paySale.getItemType() == 3) {
            // 补签卡：校验唯一性，更新user表补签卡状态
            UserDO user = userMapper.selectById(paySale.getUserId());
            if (user != null && (user.getHasSignCard() == null || user.getHasSignCard() == 0)) {
                user.setHasSignCard(1);
                userMapper.updateById(user);
            }
        }
        // 3. 修改支付状态为支付成功
        paySale.setStatus(2);
        vocPaySaleMapper.updateById(paySale);
        // 4. 返回success
        return "success";
    }

    /**
     * 用户用于获取支付结果
     *
     * @param paySaleId
     * @return
     */
    @Override
    public Integer queryTradeStatus(Long paySaleId) {
        VocPaySaleDO paySale = vocPaySaleMapper.selectById(paySaleId);
        if (paySale == null)
            return 0;
        return paySale.getStatus();
    }

    /**
     * 分页查询用户购买记录
     *
     * @param userId
     * @param pageRequest
     * @return
     */
    @Override
    public PageDTO<VocPaySaleDTO> getPaySaleHistory(Long userId, PageRequest pageRequest) {
        LambdaQueryWrapper<VocPaySaleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VocPaySaleDO::getUserId, userId)
                .eq(VocPaySaleDO::getStatus, 2)
                .eq(VocPaySaleDO::getIsDeleted, 0)
                .orderByDesc(VocPaySaleDO::getCreateTime);
        List<VocPaySaleDO> resultList;
        long total;
        Integer pageNum = pageRequest.getPageNum();
        Integer count = pageRequest.getCount();
        if (pageNum != null && count != null && pageNum > 0 && count > 0) {
            Page<VocPaySaleDO> page = new Page<>(pageNum, count);
            Page<VocPaySaleDO> result = vocPaySaleMapper.selectPage(page, wrapper);
            resultList = result.getRecords();
            total = result.getTotal();
        } else {
            resultList = vocPaySaleMapper.selectList(wrapper);
            total = resultList.size();
        }
        List<VocPaySaleDTO> dtoList = resultList.stream().map(payConverter::vocPaySaleDO2DTO)
                .collect(java.util.stream.Collectors.toList());
        return new PageDTO<>(dtoList, total);
    }

}
